package main

import (
	"context"
	"fmt"
	"sync"

	reflectPb "gitee.com/wu-jin-feng/fgin/demos/fconsul_test/client/pb"
	"github.com/gin-gonic/gin"
	"google.golang.org/grpc"
	"google.golang.org/grpc/metadata"

	"gitee.com/wu-jin-feng/fgin"
)

// 一元客户端 中间件
func fgrpcClientInterceptor() grpc.UnaryClientInterceptor {
	return func(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
		// fmt.Printf("fgrpcClientInterceptor start method:%v, req:%v, reply:%v, cc:%v, opt:%v\n\n", method, req, reply, cc, opts)
		md, ok := metadata.FromOutgoingContext(ctx)
		if !ok {
			md = metadata.MD{}
		}
		md.Append("fgrpcClientInterceptor", "fgrpcClientInterceptor")
		ctx = metadata.NewOutgoingContext(ctx, md)
		fmt.Printf("fgrpcClientInterceptor start md:%v\n\n", md)
		err := invoker(ctx, method, req, reply, cc, opts...)
		fmt.Println("fgrpcClientInterceptor end")
		return err
	}
}

func fgrpcClientInterceptorV2() grpc.UnaryClientInterceptor {
	return func(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
		// fmt.Printf("fgrpcClientInterceptorV2 start method:%v, req:%v, reply:%v, cc:%v, opt:%v\n\n", method, req, reply, cc, opts)
		md, ok := metadata.FromOutgoingContext(ctx)
		if !ok {
			md = metadata.MD{}
		}
		md.Append("fgrpcClientInterceptorv2", "fgrpcClientInterceptorv2")
		ctx = metadata.NewOutgoingContext(ctx, md)
		fmt.Printf("fgrpcClientInterceptorV2 start md:%v\n\n", md)
		err := invoker(ctx, method, req, reply, cc, opts...)
		fmt.Println("fgrpcClientInterceptorV2 end")
		return err
	}
}

// 注册客户端中间件
func registerClientMidd() {
	opts := []grpc.DialOption{
		grpc.WithChainUnaryInterceptor(
			fgrpcClientInterceptor(),
			fgrpcClientInterceptorV2(),
		),
	}
	fgin.RegisterGrpcDialOptions(opts, false, false)
}

func main() {
	f := fgin.Fgin{}
	// 注册客户端中间件
	registerClientMidd()
	r := f.GetHttpServer("./test.yaml")
	log := f.GetFginLogger()
	grpcConn, err := f.GetFgrpcClientConn("test_grpc")
	if err != nil {
		panic(err)
	}
	c := reflectPb.NewDemoServiceClient(grpcConn)
	r.GET("/test", func(ctx *gin.Context) {
		log.Info("哈哈哈哈哈")
		// a := 0
		// _ = 1 / a
		res, err := c.GetScheme(ctx, &reflectPb.GetSchemeReq{
			Path: "321222",
			Info: &reflectPb.GetSchemeRespInfo{
				Info: "哈哈哈哈",
				Name: "gogo",
			},
		})
		if err != nil {
			fgin.ReturnJson(ctx, 500, "grpc fail", err)
			return
		}
		fgin.ReturnJson(ctx, 200, res, nil)
	})

	r.GET("/test1", func(ctx *gin.Context) {
		var wg sync.WaitGroup
		for i := 0; i < 100000; i++ {
			wg.Add(1)
			func() {
				defer wg.Done()
				res, err := c.GetScheme(ctx, &reflectPb.GetSchemeReq{
					Path: "321222",
					Info: &reflectPb.GetSchemeRespInfo{
						Info: "哈哈哈哈",
						Name: "gogo",
					},
				})
				if err != nil {
					fgin.ReturnJson(ctx, 500, "grpc fail", err)
					return
				}
				fgin.ReturnJson(ctx, 200, res, nil)

			}()
		}
		wg.Wait()
	})

	f.Run(r)
}
